package redis

import (
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/golang/glog"
)

// Env redis init params.
type Env struct {
	Network     string
	Address     string
	MaxIdle     int
	MaxActive   int
	DB          int
	Auth        string
	IdleTimeout time.Duration
}

// ConnectManager func define
type ConnectManager interface {
	Init(*Env) (*redis.Pool, error)
	Destroy(*redis.Pool)
}

type redisConnectManager struct{}

// NewRedisConnectManager new a redis manager
func NewRedisConnectManager() ConnectManager {
	return new(redisConnectManager)
}

func (inst *redisConnectManager) Init(env *Env) (*redis.Pool, error) {
	if env.Network == "" {
		env.Network = "tcp"
	}
	if env.Address == "" {
		env.Address = "127.0.0.1:6379"
	}
	if env.MaxIdle == 0 {
		env.MaxIdle = 2
	}
	if env.MaxActive == 0 {
		env.MaxActive = 10
	}
	if env.IdleTimeout == 0 {
		env.IdleTimeout = 3 * time.Second
	}
	redisPool := &redis.Pool{
		Dial: func() (redis.Conn, error) {
			cache, err := redis.Dial(env.Network, env.Address)
			if err != nil {
				glog.Fatal(err)
			}
			if env.Auth != "" {
				cache.Send("Auth", env.Auth)
			}
			cache.Do("SELECT", env.DB)
			return cache, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			if err != nil {
				glog.Fatal(err)
			}
			return err
		},
		MaxIdle:     env.MaxIdle,
		MaxActive:   env.MaxActive,
		IdleTimeout: env.IdleTimeout * time.Second,
	}
	conn := redisPool.Get()
	err := redisPool.TestOnBorrow(conn, time.Now())
	if err != nil {
		return nil, err
	}
	return redisPool, nil
}

func (inst *redisConnectManager) Destroy(pool *redis.Pool) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	signal.Notify(c, syscall.SIGKILL)
	go func() {
		<-c
		pool.Close()
	}()
}
